/*
**			Heroes IV
**	  Copyright 2001, The 3DO Company
**
**      dialog_full_army.cpp
*/
// kill the 255+ character identifier warning.  Templates tend to exceed that easily.
#include "precompiled.h"
#pragma warning( disable: 4786 )

#include "dialog_full_army.h"

#include "adaptor_handler.h"
#include "army_dialog.h"
#include "basic_dialog.h"
#include "bitmap_group.h"
#include "bitmap_group_cache.h"
#include "bitmap_layer.h"
#include "bitmap_layer_window.h"
#include "blacksmith_window.h"
#include "bound_handler.h"
#include "button.h"
#include "button_cache.h"
#include "drag_creature.h"
#include "external_string.h"
#include "interface_help.h"
#include "player.h"
#include "standard_fonts.h"


// ---------------------------------------------------------
// determine if a player can place an army - and if so, where.
// ---------------------------------------------------------
static bool can_create_army( t_creature_array& army, t_adv_map_point& point )
{
	if (army.get_owner() == 0)
		return false;
	if (!army.get_owner()->can_create_army())
		return false;

	t_adventure_object const* object = army.get_adventure_object();
	if (object == 0)
		return false;

	return object->find_adjacent_space( point, army, false );
}

extern	t_button_cache			g_ok_button;
extern  t_button_cache const    k_close_button;
extern  t_bitmap_group_cache k_garrison_bitmaps;

t_dialog_full_army::t_dialog_full_army( t_window* parent )
					: t_window( k_completely_transparent, parent ),
						m_owner_army( NULL ),
						m_visitor_army( NULL )
{
}

static t_external_string const k_text_title( "title.full_army" );
static t_external_string const k_text_description( "description.full_army" );
static t_external_string const k_text_creation_allowed( "new_army_allowed.full_army" );

// ---------------------------------------------------------
//
// ---------------------------------------------------------
void t_dialog_full_army::init_dialog(  	t_creature_array & owner_army,
										t_creature_array & visitor_army )
{
	t_bitmap_layer const*   layer;
	t_window *              window;
	t_screen_point          origin(0,0);
	t_screen_point          point(0,0);
	t_screen_rect           rect;


	m_owner_army = &owner_army;
	m_visitor_army = &visitor_army;

	m_bitmaps_ptr = k_garrison_bitmaps.get();
	layer = m_bitmaps_ptr->find( "background" );
	window = new t_bitmap_layer_window( layer, origin, this );

    /*
    ** Display the visitor and owner armies
    */
    create_full_army_window();

    /*
    ** Text windows.
    */
	t_text_window* text_window_ptr;

    // Title.
	rect = m_bitmaps_ptr->find( "title" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 20 ), rect, this, k_text_title, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    // Text.
	std::string		text;
	t_adv_map_point temp_point;

	if (can_create_army( owner_army, temp_point ))
		text = k_text_creation_allowed;
	else
		text = k_text_description;

	rect = m_bitmaps_ptr->find( "text" )->get_rect() + origin;
	text_window_ptr = new t_text_window( get_font( 18 ), rect, this, text, t_pixel_24(0,0,0));
	text_window_ptr->set_center_horizontal();
	text_window_ptr->set_drop_shadow( false );

    /*
    ** Create buttons.
    */
	t_help_block const&		shared_help = get_help_block( "shared" );
	t_button            *button_ptr;
	rect = m_bitmaps_ptr->find( "ok_button" )->get_rect();
	button_ptr = new t_button( g_ok_button.get(), rect.top_left(), this );
	button_ptr->set_click_handler( bound_handler( *this, &t_dialog_full_army::close_click ));
	set_help( button_ptr , shared_help, "ok" );

    /*
    ** Set the position and display the window.
    */
	t_screen_rect parent_rect = get_parent()->get_client_rect();
    
	rect = m_bitmaps_ptr->get_rect();
	rect += (parent_rect.size() - rect.size()) / 2;
	init( rect );
}

// ---------------------------------------------------------
//
// ---------------------------------------------------------
void t_dialog_full_army::create_full_army_window()
{
	t_screen_point bottom_point;
	t_screen_rect rect = m_bitmaps_ptr->find( "garrison_rings" )->get_rect();

	bottom_point = rect.top_left();
	bottom_point.y += k_creature_top_window_height; 
    
    /*
    ** Show owner's heroes
    */
   	m_owner_window_ptr = new t_creature_array_window( bottom_point, m_owner_army,
                                        t_creature_array_window::k_bottom_row, 0, this );


    /*
    ** Show visitor heroes - show bottom first because of graphic overlap.
    */
	m_visitor_window_ptr = new t_creature_array_window( rect.top_left(),  m_visitor_army,

		t_creature_array_window::k_top_row, 0, this );

	m_owner_window_ptr->link_selection( m_visitor_window_ptr );

	m_visitor_window_ptr->set_drag_validate_handler( bound_handler( *this, &t_dialog_full_army::check_drag_drop ) );
	m_owner_window_ptr->set_drag_validate_handler( bound_handler( *this, &t_dialog_full_army::check_drag_drop ) );

   // Default select first.
    m_owner_window_ptr->select_first();
}

// ---------------------------------------------------------
// Decide if a given drag-drop operation is legal -- in 
// this case, the drag can be illegal if the troop
// cannot be removed
// ---------------------------------------------------------
void t_dialog_full_army::check_drag_drop( t_creature_array_window::t_drag_drop_validate_data const & data, bool & accept )
{
	// Can drag creatures & artifacts -- but not heroes -- in. Cannot drag heroes or artifacts out
	t_drag_creature const * drag_creature = dynamic_cast< t_drag_creature const * >( data.drag_source );

	if ( drag_creature )
	{
		if ( drag_creature->get_source_window() == data.drag_target )
		{
			// Can always rearrange within an army
			accept = true;
		} 
		else
		if ( drag_creature->get_source_window() == m_owner_window_ptr )
		{
			// make sure you can't remove a hero from the owner's army
			if ( drag_creature->get_data()->get_hero() )
			{
				accept = false;
			}
		}
		else
		//if ( target_creature->get_data()->get_hero() )
		if( (*data.drag_target->get_army())[data.drag_target_slot].get_hero() )
			accept = false;

		return;
	}

	assert( false ); // Shouldn't be any way of dragging artifacts or other stuff
					 // If there is, we need to implement tests here

	accept = true;
	return;
}

// ---------------------------------------------------------
//
// ---------------------------------------------------------
void t_dialog_full_army::close_click( t_button* button )
{
	for (int i = 0; i < t_creature_array::k_size; ++i)
	{
		t_artifact_list leftovers;
		(*m_visitor_army)[i].redistribute_artifacts( *m_owner_army, leftovers );
		
		// At least one creature should end up in the owner army, since there were 8 creatures
		// to start with!
		assert( leftovers.empty() );
	}
	if (!m_visitor_army->empty())
		create_army( *m_owner_army, *m_visitor_army );

	m_return_value = false;
	close();
}

// ---------------------------------------------------------
// create a new army adjacent to the current army, if possible
// ---------------------------------------------------------
bool create_army( t_creature_array& current_army, t_creature_array& new_army )
{
	t_adv_map_point point;

	if (!can_create_army( current_army, point ))
		return false;

	t_adventure_map* adventure_map = current_army.get_map();

	if (adventure_map == 0)
		return false;

	t_counted_ptr<t_army>	army = new t_army( &new_army );

	army->set_owner( current_army.get_owner_number() );
	army->update_state();
	army->place( *adventure_map, point );

	// NOTE: deliberately NOT calling army->trigger_events() here. This is often just
	// before combat, and we don't want to distract the player with a bunch of 
	// unexpected messages.

	return true;
}
